'''
Created on Apr 21, 2009

@author: xoon
'''

from lxml import etree

class Xml(object):
    '''The XML class is used to test,extract or insert data from/to xml
    files'''
    
    def __init__(self,filename):
        '''Constructor with an xml valid filename in argument. The path to the file
        can be either relative or absolute'''
        self.filename = filename
    
    def validate(self):
        '''Test the file given to the constructor by parsing the content and checking it with the application's dtd.
        
Return None if the file is valid or an error message in other case'''

        self.message = None
        try:
            self.xmlparser = etree.XMLParser()
            self.xmldtd = etree.DTD("miam.dtd")
            self.xmldata = etree.parse(self.filename, self.xmlparser)
            if self.xmldtd.validate(self.xmldata) != True:
                self.message = "DTD validation Error"
                # TODO : balancer les erreurs contenues dans self.xmldtd.error_log
                print self.xmldtd.error_log
        except (etree.XMLSyntaxError),e:
            self.message = "Error : Not a valid XML File"
        except (IOError, EOFError),e:
            self.message = "Error : File problem" 
        
        return self.message
   
    
    def write_data(self,dico):
            '''Fonction which writes data to "filename" xml file'''
            root = etree.Element('MIAM')
            
            pile = list()
            for i in dico:
                pile.append([root,dico[i]])
            
            while len(pile) > 0:
                elem,dic = pile.pop(0)
                child = etree.SubElement(elem, dic['type'])
                if dic.has_key('value'):
                    child.text = dic['value']
                else :
                    for i in dic.keys():
                        if i not in ['type','value']:
                            pile.append([child,dic[i]])
            
            file = None
            try:
                file = open(self.filename,'w')
                file.write('<?xml version="1.0" encoding="UTF-8"?>')
                file.write(etree.tostring(root))
            except IOError, error:
                return error[1]
            finally :
                if file != None:
                    file.close()
            
    
    def get_data(self):
        '''Return the content of the file in a dictionnary.        
    Nodes have a "type" column with it's tag in it and a dictionnary.
    Leaves have a "type" and a "value" column.
    
The file must be valid to have a correct dictionnary'''
    
        dico = {}
        self.__get_recursive_child(self.xmldata.getroot(), dico)
        return dico
    
    def __get_recursive_child(self,elem,dico):
        '''Recursive fonction with an element of the tree and the dictionnary
where data will be put in'''
    
        children = list(elem)
        dico['type'] = elem.tag
        
        if len(children) > 0:
            i = 0
            for child in children:
                dico[i] = {}
                self.__get_recursive_child(child,dico[i])
                i += 1
        else:
            dico['value'] = elem.text